﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using MediaPortal.TvServer.WebServices;
using TvLibrary.Log;

namespace TvServerPlugin
{
    public class Settings
    {
        public static string BaseDir = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
        private static string _mpDatabaseDir = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + @"\Team MediaPortal\MediaPortal\database\";

        public static int HttpPort { get; set; }
        public static int ThumbWidth { get; set; }
        public static int ThumbHeight { get; set; }
        public static string ClientPlayer { get; set; }
        public static string StreamURL { get; set; }
        public static string ScraperURL { get; set; }
        public static int PlayerType { get; set; }
        public static string WebUsername { get; set; }
        public static string WebPassword { get; set; }
        public static DBLocations DBLocations { get; set; }
        public static ThumbPaths Thumbs { get; set; }
        public static string HTDocsDirectory { get { return BaseDir + "MPWebServices\\webroot"; } }
        public static string VirtualDirectory { get { return "/"; } }
        public static List<EncoderConfig> EncoderConfigs { get; set; }

        private static string SetDbLocation(XmlNode node, string dbName)
        {
            string fn = node.Attributes["filename"].Value;
            if (!File.Exists(fn))
            {
                if (File.Exists(_mpDatabaseDir + dbName))
                    fn = _mpDatabaseDir + dbName;
                else
                    fn = "";
            }
            return fn;
        }

        public static bool LoadSettings()
        {
            try
            {
                XmlDocument doc = new XmlDocument();
                Log.WriteInfo("MPWebServices: config.xml=" + BaseDir + "\\MPWebServices\\config.xml");
                doc.Load(BaseDir + "\\MPWebServices\\config.xml");

                //Get Standard Config
                XmlNode gNode = doc.SelectSingleNode("/appconfig/config");
                HttpPort = Int32.Parse(gNode.Attributes["httpport"].Value);
                ThumbHeight = Int32.Parse(gNode.Attributes["thumbheight"].Value);
                ThumbWidth = Int32.Parse(gNode.Attributes["thumbwidth"].Value);
                ClientPlayer = gNode.Attributes["clientplayerpath"].Value;
                PlayerType = Int32.Parse(gNode.Attributes["playertype"].Value);
                ScraperURL = gNode.Attributes["scraper_url"].Value;
                
                if (gNode.Attributes["streamurl"] != null)
                    StreamURL = gNode.Attributes["streamurl"].Value;
                if (string.IsNullOrEmpty(StreamURL))
                    StreamURL = "http://" + Environment.MachineName + ":" + HttpPort.ToString();

                WebUsername = gNode.Attributes["username"].Value;
                WebPassword = gNode.Attributes["password"].Value;

                //Setup Database locations
                XmlNodeList nodes = doc.SelectNodes("/appconfig/mpdatabases/database");
                foreach (XmlNode node in nodes)
                {
                    switch (node.Attributes["name"].Value)
                    {
                        case "movies":
                            DBLocations.Movies = SetDbLocation(node, "VideoDatabaseV5.db3");
                            break;
                        case "music":
                            DBLocations.Music = SetDbLocation(node, "MusicDatabaseV11.db3");
                            break;
                        case "pictures":
                            DBLocations.Pictures = SetDbLocation(node, "PictureDatabase.db3");
                            break;
                        case "tvseries":
                            DBLocations.TVSeries = SetDbLocation(node, "TvSeriesDatabase4.db3");
                            break;
                        case "movingpictures":
                            DBLocations.MovingPictures = SetDbLocation(node, "movingpictures.db3");
                            break;
                    }
                }

                //Thumb paths
                nodes = doc.SelectNodes("/appconfig/thumbpaths/thumb");
                foreach (XmlNode node in nodes)
                {
                    switch (node.Attributes["name"].Value)
                    {
                        case "tv":
                            Thumbs.TV = node.Attributes["path"].Value;
                            break;
                        case "radio":
                            Thumbs.Radio = node.Attributes["path"].Value;
                            break;
                        case "pictures":
                            Thumbs.Pictures = node.Attributes["path"].Value;
                            break;
                    }
                }
                
                //Transcoders
                nodes = doc.SelectNodes("/appconfig/transcoders/transcoder");
                EncoderConfigs = new List<EncoderConfig>();
                foreach (XmlNode node in nodes)
                {
                    EncoderConfig cfg = new EncoderConfig(
                        node.Attributes["name"].Value, 
                        (node.Attributes["usetranscoding"].Value == "1"), 
                        node.Attributes["filename"].Value, 
                        node.Attributes["args"].Value, 
                        (TransportMethod)Int32.Parse(node.Attributes["inputmethod"].Value), 
                        (TransportMethod)Int32.Parse(node.Attributes["outputmethod"].Value));
                    EncoderConfigs.Add(cfg);
                }
            }
            catch (Exception ex)
            {
                Log.WriteError("Exception raised while loading settings:" + Environment.NewLine + ex.Message + Environment.NewLine + ex.StackTrace);
                return false;
            }
            return true;
        }

        private static void NewAttribute(XmlNode node, string name, string value)
        {
            XmlAttribute attr = node.OwnerDocument.CreateAttribute(name);
            attr.InnerText = value;
            node.Attributes.Append(attr);
        }

        private static void NewAttribute(XmlNode node, string name, bool value)
        {
            XmlAttribute attr = node.OwnerDocument.CreateAttribute(name);
            if (value)
                attr.InnerText = "1";
            else
                attr.InnerText = "0";
            node.Attributes.Append(attr);
        }

        private static void NewAttribute(XmlNode node, string name, int value)
        {
            XmlAttribute attr = node.OwnerDocument.CreateAttribute(name);
            attr.InnerText = value.ToString();
            node.Attributes.Append(attr);
        }

        private static void AddDbPath(string name, string path, XmlNode dbNode, XmlDocument doc)
        {
            XmlNode node = doc.CreateElement("database");
            NewAttribute(node, "name", name);
            NewAttribute(node, "filename", path);
            dbNode.AppendChild(node);
        }

        private static void AddThumbPath(string name, string path, XmlNode dbNode, XmlDocument doc)
        {
            XmlNode node = doc.CreateElement("thumb");
            NewAttribute(node, "name", name);
            NewAttribute(node, "path", path);
            dbNode.AppendChild(node);
        }

        public static void SaveSettings()
        {
            XmlDocument doc = new XmlDocument();
            XmlNode root = doc.CreateElement("appconfig");
            XmlNode gNode = doc.CreateElement("config");
            NewAttribute(gNode, "httpport", HttpPort);
            NewAttribute(gNode, "thumbwidth", ThumbWidth);
            NewAttribute(gNode, "thumbheight", ThumbHeight);
            NewAttribute(gNode, "clientplayerpath", ClientPlayer);
            NewAttribute(gNode, "playertype", PlayerType);
            NewAttribute(gNode, "streamurl", StreamURL);
            NewAttribute(gNode, "scraper_url", ScraperURL);
            NewAttribute(gNode, "username", WebUsername);
            NewAttribute(gNode, "password", WebPassword);

            XmlNode dbpaths = doc.CreateElement("mpdatabases");
            AddDbPath("movies", DBLocations.Movies, dbpaths, doc);
            AddDbPath("music", DBLocations.Music, dbpaths, doc);
            AddDbPath("pictures", DBLocations.Pictures, dbpaths, doc);
            AddDbPath("tvseries", DBLocations.TVSeries, dbpaths, doc);
            AddDbPath("movingpictures", DBLocations.MovingPictures, dbpaths, doc);

            XmlNode thpaths = doc.CreateElement("thumbpaths");
            AddThumbPath("tv", Thumbs.TV, thpaths, doc);
            AddThumbPath("radio", Thumbs.Radio, thpaths, doc);
            AddThumbPath("pictures", Thumbs.Pictures, thpaths, doc);

            XmlNode transcoders = doc.CreateElement("transcoders");
            foreach (EncoderConfig cfg in EncoderConfigs)
            {
                XmlNode node = doc.CreateElement("transcoder");
                NewAttribute(node, "name", cfg.DisplayName);
                NewAttribute(node, "usetranscoding", cfg.UseTranscoding);
                NewAttribute(node, "filename", cfg.FileName);
                NewAttribute(node, "args", cfg.Args);
                NewAttribute(node, "inputmethod", (int)cfg.InputMethod);
                NewAttribute(node, "outputmethod", (int)cfg.OutputMethod);
                transcoders.AppendChild(node);
            }
            root.AppendChild(gNode);
            root.AppendChild(transcoders);
            root.AppendChild(dbpaths);
            root.AppendChild(thpaths);
            doc.AppendChild(root);
            doc.Save(BaseDir + "\\MPWebServices\\config.xml");
        }
    }
}
